#pragma once

#include <AVUIGeometry3D.h>
#include <AVUIRect3D.h>

namespace AVUI {

class Point3DCollection;
class Vector3DCollection;
class PointCollection;
class Int32Collection;


class MeshGeometry3D : public Geometry3D
{
public:
    MeshGeometry3D();
    ~MeshGeometry3D();

    DECLARE_ELEMENT(MeshGeometry3D, Geometry3D);

    DECLARE_DEPENDENCY_PROPERTY_BEGIN(Positions);
        DECLARE_ATTRIBUTE_AUTOCREATE();
    DECLARE_DEPENDENCY_PROPERTY_END();
    TRefCountedPtr<Point3DCollection> get_Positions() { return (Point3DCollection*)(Object*)GetValue(get_PositionsProperty()); }
    void set_Positions(Point3DCollection* pValue) { SetValue(get_PositionsProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY_BEGIN(Normals);
        DECLARE_ATTRIBUTE_AUTOCREATE();
    DECLARE_DEPENDENCY_PROPERTY_END();
    TRefCountedPtr<Vector3DCollection> get_Normals() { return (Vector3DCollection*)(Object*)GetValue(get_NormalsProperty()); }
    void set_Normals(Vector3DCollection* pValue) { SetValue(get_NormalsProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY_BEGIN(TextureCoordinates);
        DECLARE_ATTRIBUTE_AUTOCREATE();
    DECLARE_DEPENDENCY_PROPERTY_END();
    TRefCountedPtr<PointCollection> get_TextureCoordinates() { return (PointCollection*)(Object*)GetValue(get_TextureCoordinatesProperty()); }
    void set_TextureCoordinates(PointCollection* pValue) { SetValue(get_TextureCoordinatesProperty(), (Object*)pValue); } 

    DECLARE_DEPENDENCY_PROPERTY_BEGIN(TriangleIndices);
        DECLARE_ATTRIBUTE_AUTOCREATE();
    DECLARE_DEPENDENCY_PROPERTY_END();
    TRefCountedPtr<Int32Collection> get_TriangleIndices() { return (Int32Collection*)(Object*)GetValue(get_TriangleIndicesProperty()); }
    void set_TriangleIndices(Int32Collection* pValue) { SetValue(get_TriangleIndicesProperty(), (Object*)pValue); } 

    virtual IClientRenderGeometry* GetRenderGeometry(Renderer* pRenderer);

    virtual void RayHitTestCore(RayHitTestParameters* pRayParams, FaceType::Enum hitTestableFaces) AVUI_OVERRIDE;
    virtual Rect3D get_Bounds() AVUI_OVERRIDE;

protected:

    virtual TRefCountedPtr<Freezable> CreateInstanceCore() AVUI_OVERRIDE { return object_allocate<MeshGeometry3D>().get_Ptr(); }

private:
    static void StaticConstructor();

    void UpdateCachedBounds();
    void ValidateLineHit(RayHitTestParameters* pRayParams, FaceType::Enum facesToHit, int i0, int i1, int i2, const Point3D& v0, const Point3D& v1, const Point3D& v2, const Point& barycentric);
    void ValidateRayHit(RayHitTestParameters* pRayParams, const Point3D& origin, const Vector3D& direction, float hitTime, int i0, int i1, int i2, const Point& barycentric);

    void OnRenderDeviceLost(Object* pObject, EventArgs* pEventArgs);

    IClientRenderGeometry* m_pClientGeometry;
    Rect3D m_cachedBounds;
};


}; // namespace AVUI
